#include "t0022-0.h"
#include "cui.h"

#define MODNAME     "[CPNL]"
struct cui_widget_operations __panel_ops;

void cui_panel_destroy(struct cui_widget_st *widget)
{
    if (widget != NULL) {
        struct cui_panel_st *cpanel = widget->widgetinstance;
        if (cpanel != NULL) {
            ERRSYS_INFOPRINT("[%s]%s destroy panel %p\n", widget->name, __func__, cpanel->panel);
            del_panel(cpanel->panel);
            free(cpanel);
            delwin(widget->win);
            widget->widgetinstance = NULL;
        }
        cui_widget_destroy(widget);
    }
}

struct cui_widget_st* cui_panel_dup(struct cui_widget_st* template)
{
    // struct cui_widget_st* widget = cui_widget_dup(template);
    struct cui_widget_st* widget = cui_widget_dup(template);
    struct cui_panel_st *cpanel = zmalloc(sizeof(struct cui_panel_st));
    int retval = -1;

    ERRSYS_INFOPRINT("[%s]%s create widget %p cpanel %p\n", widget->name, __func__, widget, cpanel);

    if (widget != NULL && cpanel != NULL) {
        UNSET_WIDGET_TEMPLATE(widget);
        /* create win/panel object */
        widget->win = newwin(widget->lines, widget->cols, widget->beginy, widget->beginx);
        cpanel->panel = new_panel(widget->win);
        widget->widgetinstance = cpanel;
        retval = 0;
    }

    if (retval < 0) {
        if (cpanel != NULL) {
            free(cpanel);
        }
        if (widget != NULL) {
            cui_widget_destroy(widget);
        }
    }
    return widget;
}

void cui_panel_reset_template(struct cui_widget_st* widget)
{
    struct cui_widget_st *pos, *n;
    SET_WIDGET_TEMPLATE(widget);

    list_for_each_entry_safe(pos, n, &widget->widgetlist, node) {
        pos->ops.destroy(pos);
    }
    INIT_LIST_HEAD(&widget->widgetlist);
    return;
}

int cui_panel_duplicate(struct cui_widget_st* template, int ncopies)
{
    // widget is panel template
    int retval = -1;
    int i = 0;
    ERRSYS_INFOPRINT("[%s]%s %d copies\n", template->name, __func__, ncopies);
    if (ncopies > 0) {
        for (i = 0;i < ncopies;i ++) {
            struct cui_widget_st* widget = cui_panel_dup(template);
            if (widget != NULL) {
                list_add_tail(&widget->node, &template->widgetlist);
                snprintf(widget->name, CUI_WIDGETTITLE_BUFLEN, "%s#%d", template->name, i);
            }
            else {
                goto err;
            }
        }
        retval = 0;
        goto out;
    }
err:
    if (i != ncopies) {
        struct list_head *pos, *n;
        ERRSYS_INFOPRINT("%s release %p\n", __func__, template);
        list_for_each_prev_safe(pos, n, &template->widgetlist) {
            if (i -- > 0) {
                struct cui_widget_st *widget = list_entry(pos, struct cui_widget_st, node);
                list_del(&widget->node);
                widget->ops.destroy(widget);
            }
        }
    }

out:
    return retval;
}

int cui_move_resize_panel(struct cui_widget_st* widget)
{
    if (widget != NULL) {
        struct cui_panel_st *cpanel = widget->widgetinstance;
        wresize(widget->win, widget->lines, widget->cols);
        move_panel(cpanel->panel, widget->beginy, widget->beginx);
    }
    return 0;
}

int cui_panel_rearrange(struct cui_widget_st* template, int rearrange)
{
    int retval = -1;
    int n = 0;
    if (rearrange >= PANEL_REARRANGE_ROW && rearrange <= PANEL_REARRANGE_GRID) {
        struct cui_widget_st *pos;
        list_for_each_entry(pos, &template->widgetlist, node) {
            n ++;
        }
    }
    // ERRSYS_INFOPRINT("cui_panel_rearrange\n");
    cui_dump_widget(template);

    if (n > 0) {
        int i = 0;
        struct cui_widget_st *widget;
        // struct cui_panel_st *panel;
        list_for_each_entry(widget, &template->widgetlist, node) {
            if (rearrange == PANEL_REARRANGE_ROW) {
                widget->lines = 5;
                widget->cols = template->cols;
                widget->beginx = template->beginx;
                widget->beginy = template->beginy + i * widget->lines;
                cui_dump_widget(widget);
                cui_move_resize_panel(widget);
            }
            i ++;
        }
    }
    return retval;
}

// root: "widgetlist:[]"
int cui_panel_parse(cJSON *root, struct cui_widget_st* widget)
{
    int retval = -1;
    struct cui_panel_st *cpanel = zmalloc(sizeof(struct cui_panel_st));
    int npanels = 1;
    cJSON *node;

    ERRSYS_INFOPRINT("### parsing PANEL %p %p %p...\n", widget, cpanel, &widget->widgetlist);
    if (cpanel == NULL) {
        goto err;
    }
    retval = cui_attributes_parse(root, widget, &__panel_ops, cpanel);
    if (retval == -1) {
        goto err;
    }
    widget->win = newwin(widget->lines, widget->cols, widget->beginy, widget->beginx);
    cpanel->panel = new_panel(widget->win);
 
    cui_dump_widget_hierarchy(widget);
    node = cJSON_GetObjectItem(root, CUI_CONFIELD_PANELCOUNT);
    if (cJSON_ValidNumber(node)) {
        npanels = node->valueint;
    }

    // cui_panel_reset_template(widget);
    ERRSYS_INFOPRINT("npanels %d\n", npanels);
    if (npanels > 0) {
        retval = cui_panel_duplicate(widget, npanels);
        if (retval == -1) {
            goto err;
        }
    }

    cui_dump_widget(widget);
    retval = 0;
err:
    if (retval != 0) {
        widget->ops.destroy(widget);
    }
    return retval;
}

int cui_panel_create(struct cui_widget_st *widget)
{
    if (widget != NULL) {
        ERRSYS_INFOPRINT("[%s] created lines:%d cols:%d x:%d y:%d\n", widget->name,
        widget->lines, widget->cols, widget->beginx, widget->beginy);
        widget->win = newwin(widget->lines, widget->cols, widget->beginy, widget->beginx);
        cui_dump_widget(widget);
        if (widget->win != NULL) {
            return 0;
        }
    }
    return -1;
}

void cui_panel_paint(struct cui_widget_st *widget)
{
    // widget_panel is cpanel group leader
    // ERRSYS_INFOPRINT("%s:[%s] BEGIN\n", __func__, widget->name);
    
    if (widget != NULL && IS_WIDGET_TEMPLATE(widget)) {
        struct cui_widget_st *widget_panel;
        list_for_each_entry(widget_panel, &widget->widgetlist, node) {
            WINDOW *win = widget_panel->win;
            int w, h, split_y;
            struct cui_label_st *clabel;

            /* 2 lines/cols included for the border frame */
            w = widget_panel->cols;
            h = widget_panel->lines;

            if (IS_WIDGET_HIGHLIGHT(widget_panel)) {
                wbkgdset(win, COLOR_PAIR(YELBLK));
            }
            else {
                wbkgdset(win, COLOR_PAIR(WHTBLK));
            }
            // ERRSYS_INFOPRINT("[%s] %p %p\n", widget_panel->name, win, widget_panel->win);
            if (IS_WIDGET_BORDER(widget_panel)) {
                ERRSYS_INFOPRINT("[%s] paint border\n", widget_panel->name);
                box(win, 0, 0);
            }
            /* draw title */
            cui_dump_widget(widget_panel);
            if (IS_WIDGET_TITLE(widget_panel)) {
                split_y = CUI_WIDGET_TITLESPLITTER_COLOFFSET;
                ERRSYS_INFOPRINT("[%s] paint title split line yoffset:%d xoffset:%d\n", widget_panel->name, split_y, 0);
                mvwaddch(win, split_y, 0, ACS_LTEE);
                mvwhline(win, split_y, 1, ACS_HLINE, w - 2);
                mvwaddch(win, split_y, w - 1, ACS_RTEE);
                cui_print(win, split_y - 1, 1, w - 2, widget_panel->name, WHTBLK, CUI_PRINT_ALIGNMENT_MIDDLE);
            }

            clabel = widget_panel->clabel;
            if (clabel != NULL) {
                int i;
                for (i = 0;i < widget_panel->nlabels;i ++) {
                    // ERRSYS_INFOPRINT("!!!!cui_print #%d[%s] y %d x %d\n", i, clabel[i].text, clabel[i].beginy, clabel[i].beginx);
                    cui_print(win, clabel[i].beginy, clabel[i].beginx, strlen(clabel[i].text), clabel[i].text, WHTBLK, CUI_PRINT_ALIGNMENT_MIDDLE);
                }
            }

            ERRSYS_INFOPRINT("[%s]%s x:%d y:%d cols:%d line:%d\n", widget_panel->name, __func__, widget_panel->beginx, widget_panel->beginy, w, h);
        }

		update_panels();
		doupdate();
    }

    // ERRSYS_INFOPRINT("%s:[%s] END\n", __func__, widget->name);
}

struct cui_widget_operations __panel_ops = {
    .name = "panel",
    .parse = cui_panel_parse,
    .create = cui_panel_create,
    .destroy = cui_panel_destroy,
    .paint = cui_panel_paint,
    // .keyevent = cui_window_keyevent,
};